<template>
  <div class="document-preview">
    <!-- 加载状态 -->
    <div v-if="loading" class="loading-container">
      <n-spin size="large" />
      <p class="loading-text">正在加载文档...</p>
    </div>

    <!-- 错误状态 -->
    <div v-else-if="error" class="error-container">
      <n-result status="error" title="加载失败" :description="error">
        <template #footer>
          <n-button @click="loadDocument">重新加载</n-button>
        </template>
      </n-result>
    </div>

    <!-- PDF预览 -->
    <div v-else-if="documentType === 'pdf'" class="pdf-preview">
      <div class="pdf-controls">
        <n-button-group>
          <n-button @click="previousPage" :disabled="currentPage <= 1">
            <template #icon>
              <n-icon><ChevronBackOutline /></n-icon>
            </template>
            上一页
          </n-button>
          <n-button @click="nextPage" :disabled="currentPage >= totalPages">
            下一页
            <template #icon>
              <n-icon><ChevronForwardOutline /></n-icon>
            </template>
          </n-button>
        </n-button-group>
        <div class="page-info">
          第 {{ currentPage }} 页 / 共 {{ totalPages }} 页
        </div>
        <n-button-group>
          <n-button @click="zoomOut">
            <template #icon>
              <n-icon><RemoveOutline /></n-icon>
            </template>
          </n-button>
          <n-button @click="resetZoom">
            {{ Math.round(scale * 100) }}%
          </n-button>
          <n-button @click="zoomIn">
            <template #icon>
              <n-icon><AddOutline /></n-icon>
            </template>
          </n-button>
        </n-button-group>
      </div>
      <div class="pdf-container" ref="pdfContainer">
        <canvas ref="pdfCanvas" class="pdf-canvas"></canvas>
      </div>
    </div>

    <!-- Word文档预览 -->
    <div v-else-if="documentType === 'docx'" class="docx-preview">
      <div class="docx-content" v-html="docxContent"></div>
    </div>

    <!-- Excel预览 -->
    <div v-else-if="documentType === 'xlsx'" class="xlsx-preview">
      <div class="xlsx-controls">
        <n-select v-model:value="selectedSheet" :options="sheetOptions" @update:value="renderSheet" />
      </div>
      <div class="xlsx-table-container">
        <table class="xlsx-table" v-html="xlsxContent"></table>
      </div>
    </div>

    <!-- 图片预览 -->
    <div v-else-if="documentType === 'image'" class="image-preview">
      <img :src="imageUrl" :alt="documentName" class="preview-image" />
    </div>

    <!-- Markdown预览 -->
    <div v-else-if="documentType === 'markdown'" class="markdown-preview">
      <div class="markdown-content" v-html="markdownContent"></div>
    </div>

    <!-- 文本预览 -->
    <div v-else-if="documentType === 'text'" class="text-preview">
      <pre class="text-content">{{ textContent }}</pre>
    </div>

    <!-- 不支持的文件类型 -->
    <div v-else class="unsupported-preview">
      <n-result status="info" title="不支持的文件类型" :description="`暂不支持预览 ${fileExtension} 类型的文件`">
        <template #footer>
          <n-button @click="downloadDocument">
            <template #icon>
              <n-icon><DownloadOutline /></n-icon>
            </template>
            下载文档
          </n-button>
        </template>
      </n-result>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import { NButton, NButtonGroup, NIcon, NResult, NSpin, NSelect } from 'naive-ui'
import { 
  ChevronBackOutline, 
  ChevronForwardOutline, 
  AddOutline, 
  RemoveOutline,
  DownloadOutline
} from '@vicons/ionicons5'
import * as pdfjsLib from 'pdfjs-dist'
import mammoth from 'mammoth'
import * as XLSX from 'xlsx'
import { marked } from 'marked'

// 配置PDF.js worker
try {
  pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
    'pdfjs-dist/build/pdf.worker.min.js',
    import.meta.url
  ).toString()
} catch (e) {
  // 如果在构建时无法解析，使用CDN作为备用方案
  pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/5.4.296/pdf.worker.min.js'
}

interface Props {
  documentUrl: string
  documentName: string
  documentContent?: string
  documentType?: string
}

const props = withDefaults(defineProps<Props>(), {
  documentContent: '',
  documentType: ''
})

const emit = defineEmits(['error', 'loaded'])

// 状态
const loading = ref(true)
const error = ref('')
const currentPage = ref(1)
const totalPages = ref(0)
const scale = ref(1.0)
const pdfDocument = ref<any>(null)
const docxContent = ref('')
const xlsxContent = ref('')
const selectedSheet = ref(0)
const sheetOptions = ref<Array<{ label: string; value: number }>>([])
const markdownContent = ref('')
const textContent = ref('')

// 引用
const pdfContainer = ref<HTMLElement | null>(null)
const pdfCanvas = ref<HTMLCanvasElement | null>(null)

// 计算属性
const fileExtension = computed(() => {
  if (!props.documentName) return ''
  return props.documentName.split('.').pop()?.toLowerCase() || ''
})

const documentType = computed(() => {
  if (props.documentType) return props.documentType
  
  // 根据文件扩展名判断类型
  const ext = fileExtension.value
  if (ext === 'pdf') return 'pdf'
  if (['doc', 'docx'].includes(ext)) return 'docx'
  if (['xls', 'xlsx'].includes(ext)) return 'xlsx'
  if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'].includes(ext)) return 'image'
  if (['md', 'markdown'].includes(ext)) return 'markdown'
  if (['txt', 'csv', 'json', 'xml', 'html', 'css', 'js', 'ts', 'vue', 'py', 'java', 'c', 'cpp', 'h', 'hpp'].includes(ext)) return 'text'
  
  return 'unsupported'
})

const imageUrl = computed(() => {
  if (props.documentUrl) return props.documentUrl
  if (props.documentContent && documentType.value === 'image') return props.documentContent
  return ''
})

// 方法
const loadDocument = async () => {
  loading.value = true
  error.value = ''
  
  try {
    switch (documentType.value) {
      case 'pdf':
        await loadPdf()
        break
      case 'docx':
        await loadDocx()
        break
      case 'xlsx':
        await loadXlsx()
        break
      case 'markdown':
        await loadMarkdown()
        break
      case 'text':
        await loadText()
        break
      case 'image':
        // 图片直接使用URL或内容
        break
      default:
        error.value = `不支持的文件类型: ${fileExtension.value}`
    }
  } catch (err) {
    console.error('加载文档失败:', err);
    error.value = `加载文档失败: ${err instanceof Error ? err.message : '未知错误'}`
    emit('error', error.value)
  } finally {
    loading.value = false
  }
}

const loadPdf = async () => {
  if (!props.documentUrl && !props.documentContent) {
    throw new Error('PDF文档URL或内容不能为空')
  }
  
  const pdfData = props.documentContent ? atob(props.documentContent) : await fetchPdfData(props.documentUrl)
  const loadingTask = pdfjsLib.getDocument({ data: pdfData })
  pdfDocument.value = await loadingTask.promise
  totalPages.value = pdfDocument.value.numPages
  currentPage.value = 1
  await renderPdfPage(currentPage.value)
}

const fetchPdfData = async (url: string): Promise<string> => {
  const response = await fetch(url)
  const arrayBuffer = await response.arrayBuffer()
  return new TextDecoder().decode(arrayBuffer)
}

const renderPdfPage = async (pageNum: number) => {
  if (!pdfDocument.value || !pdfCanvas.value) return
  
  const page = await pdfDocument.value.getPage(pageNum)
  const viewport = page.getViewport({ scale: scale.value })
  
  const canvas = pdfCanvas.value
  const context = canvas.getContext('2d')
  if (!context) return
  
  canvas.height = viewport.height
  canvas.width = viewport.width
  
  const renderContext = {
    canvasContext: context,
    viewport: viewport
  }
  
  await page.render(renderContext).promise
}

const loadDocx = async () => {
  if (!props.documentUrl && !props.documentContent) {
    throw new Error('Word文档URL或内容不能为空')
  }
  
  let arrayBuffer: ArrayBuffer
  if (props.documentContent) {
    // 假设内容是base64编码的
    const binaryString = atob(props.documentContent)
    const bytes = new Uint8Array(binaryString.length)
    for (let i = 0; i < binaryString.length; i++) {
      bytes[i] = binaryString.charCodeAt(i)
    }
    arrayBuffer = bytes.buffer
  } else {
    const response = await fetch(props.documentUrl)
    arrayBuffer = await response.arrayBuffer()
  }
  
  const result = await mammoth.convertToHtml({ arrayBuffer })
  docxContent.value = result.value
}

const loadXlsx = async () => {
  if (!props.documentUrl && !props.documentContent) {
    throw new Error('Excel文档URL或内容不能为空')
  }
  
  let arrayBuffer: ArrayBuffer
  if (props.documentContent) {
    // 假设内容是base64编码的
    const binaryString = atob(props.documentContent)
    const bytes = new Uint8Array(binaryString.length)
    for (let i = 0; i < binaryString.length; i++) {
      bytes[i] = binaryString.charCodeAt(i)
    }
    arrayBuffer = bytes.buffer
  } else {
    const response = await fetch(props.documentUrl)
    arrayBuffer = await response.arrayBuffer()
  }
  
  const workbook = XLSX.read(arrayBuffer, { type: 'array' })
  
  // 准备工作表选项
  sheetOptions.value = workbook.SheetNames.map((name, index) => ({
    label: name,
    value: index
  }))
  
  if (sheetOptions.value.length > 0) {
    selectedSheet.value = 0
    renderSheet(0)
  }
}

const renderSheet = (sheetIndex: number) => {
  if (!props.documentContent && !props.documentUrl) return
  
  let arrayBuffer: ArrayBuffer
  if (props.documentContent) {
    const binaryString = atob(props.documentContent)
    const bytes = new Uint8Array(binaryString.length)
    for (let i = 0; i < binaryString.length; i++) {
      bytes[i] = binaryString.charCodeAt(i)
    }
    arrayBuffer = bytes.buffer
  } else {
    // 这里应该从缓存或重新获取
    return
  }
  
  const workbook = XLSX.read(arrayBuffer, { type: 'array' })
  const sheetName = workbook.SheetNames[sheetIndex]
  const worksheet = workbook.Sheets[sheetName]
  const htmlTable = XLSX.utils.sheet_to_html(worksheet)
  xlsxContent.value = htmlTable
}

const loadMarkdown = async () => {
  if (props.documentContent) {
    markdownContent.value = await marked(props.documentContent)
  } else if (props.documentUrl) {
    const response = await fetch(props.documentUrl)
    const text = await response.text()
    markdownContent.value = await marked(text)
  } else {
    throw new Error('Markdown内容不能为空')
  }
}

const loadText = async () => {
  if (props.documentContent) {
    textContent.value = props.documentContent
  } else if (props.documentUrl) {
    const response = await fetch(props.documentUrl)
    const text = await response.text()
    textContent.value = text
  } else {
    throw new Error('文本内容不能为空')
  }
}

// PDF控制方法
const previousPage = () => {
  if (currentPage.value > 1) {
    currentPage.value--
    renderPdfPage(currentPage.value)
  }
}

const nextPage = () => {
  if (currentPage.value < totalPages.value) {
    currentPage.value++
    renderPdfPage(currentPage.value)
  }
}

const zoomIn = () => {
  scale.value = Math.min(scale.value + 0.25, 3.0)
  renderPdfPage(currentPage.value)
}

const zoomOut = () => {
  scale.value = Math.max(scale.value - 0.25, 0.5)
  renderPdfPage(currentPage.value)
}

const resetZoom = () => {
  scale.value = 1.0
  renderPdfPage(currentPage.value)
}

const downloadDocument = () => {
  if (props.documentUrl) {
    const link = document.createElement('a')
    link.href = props.documentUrl
    link.download = props.documentName
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  }
}

// 监听props变化
watch(() => props.documentUrl, () => {
  loadDocument()
})

watch(() => props.documentContent, () => {
  loadDocument()
})

// 生命周期
onMounted(() => {
  loadDocument()
})
</script>

<style scoped>
.document-preview {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.loading-container, .error-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 20px;
}

.loading-text {
  margin-top: 16px;
  color: #666;
}

/* PDF预览样式 */
.pdf-preview {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.pdf-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px;
  background-color: #f5f5f5;
  border-bottom: 1px solid #e0e0e0;
}

.page-info {
  font-size: 14px;
  color: #666;
}

.pdf-container {
  flex: 1;
  overflow: auto;
  display: flex;
  justify-content: center;
  padding: 20px;
  background-color: #f5f5f5;
}

.pdf-canvas {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  background-color: white;
}

/* Word文档预览样式 */
.docx-preview {
  flex: 1;
  overflow: auto;
  padding: 20px;
  background-color: white;
}

.docx-content {
  max-width: 800px;
  margin: 0 auto;
  line-height: 1.6;
}

/* Excel预览样式 */
.xlsx-preview {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.xlsx-controls {
  padding: 12px;
  background-color: #f5f5f5;
  border-bottom: 1px solid #e0e0e0;
}

.xlsx-table-container {
  flex: 1;
  overflow: auto;
  padding: 20px;
  background-color: #f5f5f5;
}

.xlsx-table {
  border-collapse: collapse;
  background-color: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.xlsx-table td, .xlsx-table th {
  border: 1px solid #e0e0e0;
  padding: 8px 12px;
  text-align: left;
}

.xlsx-table th {
  background-color: #f5f5f5;
  font-weight: bold;
}

/* 图片预览样式 */
.image-preview {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 20px;
  background-color: #f5f5f5;
}

.preview-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* Markdown预览样式 */
.markdown-preview {
  flex: 1;
  overflow: auto;
  padding: 20px;
  background-color: white;
}

.markdown-content {
  max-width: 800px;
  margin: 0 auto;
  line-height: 1.6;
}

/* 文本预览样式 */
.text-preview {
  flex: 1;
  overflow: auto;
  padding: 20px;
  background-color: white;
}

.text-content {
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* 不支持的文件类型样式 */
.unsupported-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 20px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .pdf-controls {
    flex-direction: column;
    gap: 10px;
  }
  
  .pdf-container {
    padding: 10px;
  }
  
  .docx-preview, .markdown-preview, .text-preview {
    padding: 10px;
  }
}
</style>